Passed
Push — main ( d53ef8...c82fb0 )
by Andrii
01:47
created

index.ts ➔ main   B

Complexity

Conditions 7

Size

Total Lines 52
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 42
dl 0
loc 52
rs 7.472
c 0
b 0
f 0
cc 7

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
import type { PathLike } from "fs"
2
import { sync } from "globby"
3
import { appenderSync, arr2line, createLineReader, templateLine } from "../utils"
4
5
export {
6
  readMd
7
}
8
9
if (!module.parent)
10
  main()
11
12
async function main() {
13
  const templatesDir = `${__dirname}/template/`
14
  , files = sync(`**/*`, {
15
    "gitignore": true,
16
    "cwd": templatesDir
17
  })
18
  , vars = await readMd(`${__dirname}/input.md`)
19
20
  await appenderSync(`${__dirname}/output/input.env`)(...vars[""])
21
22
  for (const file of files) {
23
    const outputFile = `${__dirname}/output/${file}`
24
    , reader = createLineReader(`${templatesDir}${file}`)
25
    , append = appenderSync(outputFile)
26
27
    for await (const line of reader) {
28
      const templ = templateLine<"type"|"prefix">(line)
29
30
      if (!templ) {
31
        await append(line, "\n")
32
        continue
33
      }
34
35
      const {
36
        indentation,
37
        type = "",
38
        prefix = ""
39
      } = templ
40
41
      if (!(type in vars))
42
        throw Error(`Unknown type: "${type}"`)
43
44
      const vars4type = vars[type]
45
46
      await append(
47
        ...Object.keys(vars4type)
48
        .map(e => {
49
          const status = vars4type[e]
50
51
          return arr2line(
52
            indentation,
53
            status && status !== "-" ? "" : "#",
54
            prefix,
55
            e
56
          )
57
        })
58
      )
59
    }
60
  }
61
62
  return files
63
}
64
65
async function readMd(path: PathLike) {
66
  const reader = createLineReader(path)
67
  //@ts-expect-error
68
  , $return: {
69
    //@ts-expect-error
70
    "": string[]
71
    [x: string]: Record<string, string> //string[] | boolean
72
  } = {"": [] as string[]}
73
74
  let headers: undefined|string[]
75
76
  for await (const line of reader) {
77
    if (!line.match(/^\|([^|]*\|)+$/)) {
78
      headers = undefined
79
      continue
80
    }
81
82
    if (headers === undefined) {
83
      headers = line.split(/\s*\|\s*/)
84
      headers.shift()
85
      headers.length--
86
87
      const {length} = headers
88
      for (let i = 0; i < length; i++) {
89
        const header = headers[i]
90
91
        if (!header)
92
          continue
93
94
        $return[header] = {}
95
      }
96
97
      continue
98
    }
99
100
    if (line.match(/^\|(\s*\-+\s*\|)+$/))
101
      continue
102
103
    const cellParser = /[^\|]+/g
104
105
    let i = -1
106
    , key: string
107
    , cell: string|undefined
108
109
    while (cell = cellParser.exec(line)?.[0]) {
110
      i++
111
112
      const trimmed = cell
113
      .replace(/(^ +| +$)/g, '')
114
      .replace("&nbsp;", " ")
115
      .replace("&emsp;", "\t")
116
117
      if (i === 0) {
118
        if (!trimmed)
119
          break
120
121
        key = trimmed
122
        $return[""].push(trimmed)
123
        continue
124
      }
125
126
      if (!trimmed)
127
        continue
128
129
      $return[headers[i]][key!] = trimmed
130
    }
131
  }
132
133
  return $return
134
}
135